#include "head.h"
/* Usage:  */
// 通过本地socket向对应的子进程发一个net_fd信息
// 第一个参数：main进程和工作进程用来通信的本地文件描述符
// 第二个参数：main进程accept的客户端连接对象的文件描述符
// 通过本地socket向指定的子进程发送一个与net_fd相关的信息  
int sendMsg(int local_socket, int net_fd, int flag) {  
    struct msghdr msg; // 消息头结构体  
    bzero(&msg, sizeof(msg)); // 清空消息头  
    
    // 准备正文信息  
    struct iovec vec[1]; // 创建一个iovec结构数组  
    vec[0].iov_base = &flag; // 指向flag变量的内存地址  
    vec[0].iov_len = sizeof(int); // 数据长度为int的大小  

    msg.msg_iov = vec; // 设置消息的iov  
    msg.msg_iovlen = 1; // iovec数组的长度为1  

    // 准备控制信息  
    struct cmsghdr *cms = (struct cmsghdr *) malloc(CMSG_LEN(sizeof(int))); // 动态分配控制信息结构体  
    cms->cmsg_len = CMSG_LEN(sizeof(int)); // 指明控制信息结构体的大小  
    cms->cmsg_level = SOL_SOCKET; // 指定控制信息级别为socket  
    cms->cmsg_type = SCM_RIGHTS; // 指定控制信息类型为SCM_RIGHTS（传递文件描述符）  

    void *p = CMSG_DATA(cms); // 获取控制数据的指针  
    int *fd = (int *)p; // 将该指针转换为int指针，指向文件描述符  
    *fd = net_fd; // 将net_fd的值赋给控制数据  

    msg.msg_control = cms; // 设置控制信息  
    msg.msg_controllen = CMSG_LEN(sizeof(int)); // 设置控制信息长度  

    sendmsg(local_socket, &msg, 0); // 发送消息  

    return 0;  
}  

// 子进程读取父进程通过本地socket发送过来的新的客户端socket对象  
int recvMsg(int local_socket, int *net_fd, int *flag) {  
    struct msghdr msg; // 消息头结构体  
    bzero(&msg, sizeof(msg)); // 清空消息头  

    // 准备正文信息  
    int *num = (int *)malloc(sizeof(int)); // 动态分配内存用于接收flag  
    struct iovec vec[1]; // 创建一个iovec结构数组  
    vec[0].iov_base = num; // 指向num变量的内存地址  
    vec[0].iov_len = sizeof(int); // 数据长度为int的大小  

    msg.msg_iov = vec; // 设置消息的iov  
    msg.msg_iovlen = 1; // iovec数组的长度为1  

    // 准备控制信息  
    struct cmsghdr *cms = (struct cmsghdr *) malloc(CMSG_LEN(sizeof(int))); // 动态分配控制信息结构体  
    cms->cmsg_len = CMSG_LEN(sizeof(int)); // 指明控制信息结构体的大小  
    cms->cmsg_level = SOL_SOCKET; // 指定控制信息级别为socket  
    cms->cmsg_type = SCM_RIGHTS; // 指定控制信息类型为SCM_RIGHTS（传递文件描述符）  

    msg.msg_control = cms; // 设置控制信息  
    msg.msg_controllen = CMSG_LEN(sizeof(int)); // 设置控制信息长度  

    recvmsg(local_socket, &msg, 0); // 接收消息  

    // 指向cmg_data的起始指针
    void *p = CMSG_DATA(cms); // 获取控制数据的指针  
    int *fd = (int *)p; // 将控制数据指针转换为int指针  

    // 子进程的net_fd
    // 将父进程通过 socket 发送来的文件描述符传递回子进程，使子进程可以使用这个文件描述符与新客户端进行通信。
    *net_fd = *fd; // 将接收到的net_fd赋值给调用者  

    *flag = *num; // 将接收到的flag赋值给调用者  

    free(num); // 释放分配的内存  
    return 0; // 返回0表示成功  
}
